package org.mvnsearch.rsocket.requester;

import io.rsocket.metadata.WellKnownMimeType;
import org.mvnsearch.account.AccountService;
import org.mvnsearch.account.UserService;
import org.mvnsearch.spring.boot.rsocket.RSocketRemoteServiceBuilder;
import org.springframework.boot.rsocket.messaging.RSocketStrategiesCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.core.codec.Decoder;
import org.springframework.http.MediaType;
import org.springframework.http.codec.json.Jackson2JsonDecoder;
import org.springframework.http.codec.json.Jackson2JsonEncoder;
import org.springframework.http.codec.protobuf.ProtobufDecoder;
import org.springframework.http.codec.protobuf.ProtobufEncoder;
import org.springframework.messaging.rsocket.RSocketRequester;
import org.springframework.messaging.rsocket.RSocketStrategies;
import org.springframework.util.MimeType;
import org.springframework.util.MimeTypeUtils;

import com.fasterxml.jackson.databind.ObjectMapper;

import java.net.URI;
import java.util.List;

/**
 * rsocket configuration
 *
 * @author linux_china
 */
@Configuration
public class RSocketConfiguration {
	private static final MediaType[] SUPPORTED_TYPES = { MediaType.APPLICATION_JSON,
			new MediaType("application", "*+json") };
	
	@Bean("protoRSocketStrategies")
	@Order(1)
	public RSocketStrategiesCustomizer protoBufRSocketStrategyCustomizer(ObjectMapper objectMapper) {
		return (strategy) -> {
			strategy.decoder(new ProtobufDecoder());
			strategy.encoder(new ProtobufEncoder());
			strategy.decoder(new Jackson2JsonDecoder(objectMapper, SUPPORTED_TYPES));
			strategy.encoder(new Jackson2JsonEncoder(objectMapper, SUPPORTED_TYPES));
		};
	}
	
    @Bean
    public RSocketRequester rsocketRequester(RSocketStrategies strategies) {
        MimeType mimeType = MimeTypeUtils.parseMimeType(WellKnownMimeType.APPLICATION_JSON.getString());
        List<Decoder<?>> decoders = strategies.decoders();
        if(decoders!=null ) {
        	for (Decoder<?> decoder : decoders) {
				List<MimeType> decodableMimeTypes = decoder.getDecodableMimeTypes();
				System.out.println(decodableMimeTypes.stream().map(MimeType::toString));
			}
        }
        return RSocketRequester.builder()
                .dataMimeType(mimeType)//MimeTypeUtils.APPLICATION_JSON
              
                .metadataMimeType(MimeType.valueOf(WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString()))
                
                .rsocketStrategies(strategies)
                .tcp("127.0.0.1", 42252);
               //.websocket(URI.create("ws://127.0.0.1:8088/rsocket"));
    }

    @Bean
    public AccountService accountService(RSocketRequester rsocketRequester) {
        return RSocketRemoteServiceBuilder.client(rsocketRequester, AccountService.class).build();
    }

    @Bean
    public UserService userService(RSocketRequester rsocketRequester) {
        return RSocketRemoteServiceBuilder.client(rsocketRequester, UserService.class).build();
    }
}
